與 Lodash.js 類似, Ramda.js 是一個專門以 FP 模式設計出來的函式庫,與 Lodash 不同的是,Ramda 所提供的函式預設就已經柯里化了,這讓開發者可以更用彈性的去使用這個函式庫。
如果我們要在自己程式碼中引入 Ramda.js ,可以使用以下方式:
$ npm install ramda
透過套件管理工具 NPM 進行安裝後,再透過 ES Module 的方式將函式庫引入使用:
import * as R from "ramda";
接著我們就可以透過 R
變數進行 Ramda 方法的取用了!
當然,Ramda 也可以透過 CDN 的方式引入:
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
透過 CDN 引入的 Ramda.js,同樣使用 R
變數來進行方法的取用,那麼就讓我們來看看 Ramda 提供了什麽樣的方法吧!
R.type
檢查資料型別:相較於 Lodash is
系列開頭的方法,我認為 Ramda 的 R.type()
方法更加的泛用,這樣就不需要再花時間找指定型別的相對應方法了:
R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type('s'); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(new Date); //=> "Date"
R.flip
翻轉參數順序:在柯里化的過程中,我們會發現參數的順序會決定我們要固定住哪個參數,問題來了,萬一在某些狀況下我們想固定的參數是不一樣的怎麼辦?
在 Ramda 中,我們可以使用 R.flip() 將函式中的第一個參數及第二個參數的位置翻轉過來,這樣我們就可以依照情境的不同,選擇自己要固定第一個還是第二個參數:
const mergeThree = (a, b, c) => [].concat(a, b, c);
mergeThree(1, 2, 3); //=> [1, 2, 3]
R.flip(mergeThree)(1, 2, 3); //=> [2, 1, 3]
**R.flatten
攤平陣列結構:**在 FP 中,我們仰賴資料層級結構一致的資料,這樣才可以進行重複的運算,與 Lodash 一樣,Ramda 也提供了 flatten()
進行深層的陣列結構攤平:
R.flatten([[{a: 1}], 2, 3, 4, 5, 6, [7, 8, [9, [10, 11], 12]]]);
//=> [{ a: 1}, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
R.intersection
篩選兩陣列之相等值:在 Ramda 中,我們可以透過 intersection() 方法,將兩陣列中的相同值進行比對後,篩選出值相等的內容回傳至新陣列:
R.intersection([{a: 1, b: { c: 1}},2,3,4], [{a: 1, b: { c: 1}}, 7,6,5,4,3]);
//=> [{"a": 1, "b": {"c": 1}}, 3, 4]
此時我們就會獲得一個全新的陣列,其中帶有兩陣列「值相等」的內容。
看到這你可能會發現:「咦?兩陣列中的物件,正常來說不是不應該相等嗎?」
為什麼換到 Ramda 中,物件傳參考的特性怎麼就不一定適用了?
這裡可以發現另外一個 Ramda 與 Lodash 最大的不同在於:Ramda 重視「值」的本身與貼近 FP 設計模式的實作,所以在這個方法中我們才會獲得兩陣列中「值相等」的物件。
不曉得有沒有人跟我一樣,在一開始看到這兩個函式庫所提供的方法時,腦袋跳出三個問號:「為什麼 Lodash 跟 Ramda 這麼像?」
儘管這兩個函式庫「看起來」真的很相似,認真看下來會發現他們的訴求還是有所差異,舉例來說,在 Lodash 中提供大量使用二分法的篩選方法,這讓前端開開發者在使用純函式進行程式碼管理之餘,還能使用效能較佳的方法進行演算,這一點是 Ramda 比較沒有做到的。
在 stack overflow 社群中,也有人針對這兩個函式庫的差異提出疑問,而 Ramda 的開發者 Scott Sauyet 是這麼說的:「比起效能,Ramda 更關注簡單、乾淨的 API 設計。Ramda 認為一個函式只能做一件事,這造就了 Ram 相對簡單的介面(interface)。」
以我自己使用下來的經驗,確實如同 Scott Sauyet 所述,Ramda 所提供的函式更加簡潔,也比 Lodash 更貼近了 FP 設計模式,所以可以看到更多高階函式與複合函式進階應用。
我認為這有好處也有壞處,好處在於:對 FP 熟悉的開發者來說,有更多既有的工具可以重複組合使用,壞處也同時產生:對 FP 不熟,或是沒那麼多經驗的開發者來說,Ramda.js 有點過於彈性了,缺凡語意的函式往往讓程式碼的易讀性降低,撇除這一點,Ramda 真的是一個很值得開發者學習及使用的函式庫。
對我來說 Lodash 更新手友善了一點,大部分的方法都很語意化,實務中遇到一些難解的邏輯運算時,Lodash 是一個很好的教科書,沒事翻一翻也會有一些靈感。
相比下來,Ramda 對我來說有點進階,也許是對 FP 了解不夠深入,許多 Ramda 方法比較難讓我聯想到實務上可以怎麼使用,甚至有些方法可以透過 JavaScript 的運算子所做到,多引入一個方法反而不那麼直覺。
Ramda 的開發者 Scott Sauyet 也提到:「這兩個函式庫沒有誰比較好,端看開發者的需求而定。」
簡單聊完了這兩個函式庫,這個系列的文章也差不多到了尾聲,然而 FP 的學問深的很,還有一些我們所沒有提及的內容,就讓我們在下一個章節做個小總結吧!